package org.agony2d.gpu {
	import flash.geom.Matrix;
	import org.agony2d.debug.Logger;
	import org.agony2d.gpu.core.GroupAA;
	import org.agony2d.gpu.core.MatrixProp;
	import org.agony2d.gpu.core.NodeAA;
	import org.agony2d.core.agony_internal;
	import org.agony2d.gpu.core.VertexConvergence;
	
	use namespace agony_internal;
	
	/** [ FusionAA ]
	 *  [◆]
	 *  	1.  numNodes
	 *  [◆◆]
	 *  	1.  addNode
	 *  	2.  addNodeAt
	 *  	3.  getNodeAt
	 *  	4.  getNodeIndex
	 *  	5.  setNodeIndex
	 *  	6.  swapNodes
	 *  	7.  swapNodesAt
	 *  	8.  killAllNodes
	 */
public class FusionAA extends NodeAA {
	
	public function get numNodes() : int {
		return m_numNodes
	}
	
	public function addNode( node:NodeAA ) : void {
		this.doValidateNode(node)
		m_nodeList[m_numNodes++] = node
	}
	
	public function addNodeAt( node:NodeAA, index:int ) : void {
		this.doValidateNode(node)
		m_nodeList.splice(index, 0, node)
		m_numNodes++
	}
	
	public function getNodeAt( index:int ) : NodeAA {
		return m_nodeList[index]
	}
	
	public function getNodeIndex( node:NodeAA ) : int {
		return m_nodeList.indexOf(node)
	}
	
	public function setNodeIndex( node:NodeAA, index:int ) : void {
		var oldIndex:int
		
		oldIndex = m_nodeList.indexOf(node)
		if (oldIndex != index) {
			m_nodeList.splice(oldIndex, 1)
			m_nodeList.splice(index, 0, node)
		}
	}
	
	public function swapNodes( nodeA:NodeAA, nodeB:NodeAA ) : void {
		var indexA:int, indexB:int
		
		indexA = m_nodeList.indexOf(nodeA)
		indexB = m_nodeList.indexOf(nodeB)
		this.swapNodesAt(indexA, indexB)
	}
	
	public function swapNodesAt( indexA:int, indexB:int ) : void {
		var tmpNode:NodeAA
		
		if (indexA != indexB) {
			tmpNode             =  m_nodeList[indexA]
			m_nodeList[indexA]  =  m_nodeList[indexB]
			m_nodeList[indexB]  =  tmpNode
		}
	}
	
	public function killAllNodes() : void {
		var i:int
		
		while (i < m_numNodes) {
			m_nodeList[i++].dispose()
		}
		m_nodeList.length = m_numNodes = 0
	}
	
	
	agony_internal var m_nodeList:Array = []
	agony_internal var m_numNodes:int
	
	
	
	override agony_internal function dispose() : void {
		var i:int
		
		while (i < m_numNodes) {
			m_nodeList[i++].dispose()
		}
		super.dispose()
	}
	
	agony_internal function doValidateNode( node:NodeAA ) : void {
		if (node.m_parent) {
			if (!(node is GroupAA) && node.m_fullTexture != m_fullTexture) {
				Logger.reportError(this, "doValidateNode", "Full texture alters...!!")
			}
			node.m_parent.removeNode(node)
			node.m_altered = true
		}
		else if (!(node is GroupAA)) {
			node.m_fullTexture = m_fullTexture
		}
		node.m_world = m_world
		node.m_parent = this
	}
	
	override agony_internal function render( vertexChanged:Boolean, tinted:Boolean ) : void {
		if (m_numNodes <= 0 || m_invisible) {
			return
		}
		this.doExtractNodes(vertexChanged, tinted)
	}
	
	agony_internal function doExtractNodes( vertexChanged:Boolean, tinted:Boolean ) : void {
		var i:int
		
		g_matrixQueue = g_matrixQueue.next
		if (m_altered) {
			this.updateNodeMatrix()
			vertexChanged = true
		}
		g_matrixQueue.copyFrom(m_matrix)
		g_matrixQueue.concat(g_matrixQueue.prev)
		m_cachedAlpha = m_alpha * m_parent.m_alpha
		while ((m_numNodes - i) % 8) {
			m_nodeList[i++].render(vertexChanged, tinted)
		}
		while (i < m_numNodes) {
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
			m_nodeList[i++].render(vertexChanged, tinted)
		}
		g_matrixQueue = g_matrixQueue.prev
	}
	
	override agony_internal function removeNode( node:NodeAA ) : void {
		var index:int
		
		index = m_nodeList.indexOf(node)
		m_nodeList.splice(index, 1)
		--m_numNodes
	}
	
	override agony_internal function checkCollisionNode( localX:Number, localY:Number, forInteract:Boolean ) : NodeAA {
		var node:NodeAA
		var matrix:Matrix
		var l:int
		
		if (forInteract && m_intouchable) {
			return null
		}
		if (m_collisionMethod != null) {
			return m_collisionMethod(localX, localY)
		}
		l = m_numNodes
		matrix = cachedMatrix
		while (--l > -1) {
			node = m_nodeList[l]
			matrix.copyFrom(node.m_matrix)
			matrix.invert()
			node = node.checkCollisionNode(matrix.a * localX + matrix.c * localY + matrix.tx, matrix.d * localY + matrix.b * localX + matrix.ty, forInteract)
			if (node) {
				return node
			}
		}
		return null
	}
}
}